﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary
{
    /// <summary>
    /// This class provides the development of a multidimensional Taylor series by using first and second 
    /// partial derivatives.
    /// </summary>
    [Serializable]
    public class MultidimensionalTaylorSeriesDevelopment : IMultidimensionalTaylorSeriesDevelopment
    {
        /// <summary>
        /// The point around the series should approximate the function.
        /// </summary>
        private GeneralVector a;

        /// <summary>
        /// The function, which the series should approximate.
        /// </summary>
        private HardMultivariateRealFunction function;

        /// <summary>
        /// Initializes a new instance of the <see cref="MultidimensionalTaylorSeriesDevelopment"/> class.
        /// </summary>
        /// <param name="a">The point around the series should approximate the function.</param>
        /// <param name="function">The function, which the series should approximate.</param>
        public MultidimensionalTaylorSeriesDevelopment(GeneralVector a, HardMultivariateRealFunction function)
        {
            if (function == (HardMultivariateRealFunction) null)
            {
                throw new ArgumentNullException("function");
            }

            this.a = a;
            this.function = function;
        }

        /// <summary>
        /// Gets or sets the point around the series should approximate the function.
        /// </summary>
        /// <value>The point around the series should approximate the function.</value>
        public GeneralVector A
        {
            get { return this.a; }
            set { this.a = value; }
        }

        /// <summary>
        /// Gets or sets the function, which the series should approximate.
        /// </summary>
        /// <value>The function, which the series should approximate.</value>
        public HardMultivariateRealFunction Function
        {
            get { return this.function; }
            set { this.function = value; }
        }

        /// <summary>
        /// Develops the series, by using first and second partial derivatives.
        /// </summary>
        /// <returns>The developed series.</returns>
        public MultidimensionalTaylorSeries DevelopSeries()
        {
            RealJacobianExtrapolationApproximator firstDerivativeApproximator =
                new RealJacobianExtrapolationApproximator(this.function);
            RealHessianExtrapolationApproximator secondDerivativeApproximator =
                new RealHessianExtrapolationApproximator(this.function);

            return new MultidimensionalTaylorSeries(this.a, firstDerivativeApproximator.Approximate(this.a),
                                                    secondDerivativeApproximator.Approximate(this.a, false),
                                                    this.function);
        }
    }
}